importPackage(Packages.de.elo.ix.client);
//@include lib_Class.js
//@include lib_sol.common.SordUtils.js
//@include lib_sol.common.RepoUtils.js
//@include lib_sol.common.WfUtils.js
//@include lib_sol.common.StringUtils.js
//@include lib_sol.common.ObjectUtils.js
//@include lib_sol.common.CounterUtils.js
//@include lib_sol.common.Template.js
//@include lib_sol.common.TranslateTerms.js
//@include lib_sol.common.ObjectFormatter.js
//@include lib_sol.common.ix.RfUtils.js
//@include lib_sol.common.ix.FunctionBase.js
//@include lib_sol.common.ConnectionUtils.js
var logger = sol.create("sol.Logger", { scope: "sol.common.ix.functions.Set" }); // eslint-disable-line one-var
/**
* Edits an existing object by changing the mask or setting different values.
*
* # As workflow node
*
* ObjId is set based on the element that the workflow is attached to.
*
* The timeZone parameter is currently not supported in conjunction with `asAdmin`
* because we don't want to rewrite the clientInfo of the adminConnection temporarily
*
* Following configuration should be applied to the comments field for a mask and field update:
*
* ## Example
*
* {
* "entries": [{
* "type": "MASK", // changes the mask of the sord, if defined more than once, the first one will be used
* "value": "Basic Entry"
* }, {
* "type": "SORD",
* "key": "name",
* "value": "Contract {{sord.objKeys.CONTRACT_NAME}} - {{count 'MY_CONTRACT_COUNTER'}}",
* "useTemplating": true
* }, {
* "type": "GRP",
* "key": "CONTRACT_STATUS",
* "value": "D",
* "useDynKwl": true,
* "dynKwlCfg": {
* "filterColumn": 0,
* "returnColumn": 2
* },
* "onlyIfEmpty": true
* }, {
* "type": "MAP",
* "key": "USER",
* "value": "Bill Gates",
* }, {
* "type": "WFMAP",
* "key": "USER",
* "value": "Steve Jobs"
* }, {
* "type": "WF",
* "key": "STATUS",
* "value": "CREATE"
* }]
* }
*
* Following configuration should be applied to the comments field and will set a value from the fields KWL starting with '3'
*
* {
* "entries": [{
* "type": "GRP",
* "key": "INVOICE_STATUS",
* "value": "3",
* "useKwl": true
* }]
* }
*
* Following configuration will set a field from the fields dynamic KWL staring with 'M' (e.g. M - month) from a localized dynamic KWL
*
* {
* "type": "GRP",
* "key": "REMINDER_PERIOD_UNIT",
* "value": "M",
* "useDynKwl": true,
* "dynKwlCfg": {
* "returnColumn": 2,
* "filterColumn": 0
* }
* }
*
* # As IX function call
*
* In addition to the workflow node configuration the objId must be passed.
*
* sol.common.IxUtils.execute("RF_sol_function_Set", {
* objId: "4711",
* asAdmin: true,
* entries: [{
* type: "GRP",
* key: "INVOICE_STATUS",
* value: "3",
* useKwl: true
* }]
* });
*
*
* @eloix
* @requires sol.Logger
* @requires sol.common.SordUtils
* @requires sol.common.JsonUtils
* @requires sol.common.RepoUtils
* @requires sol.common.StringUtils
* @requires sol.common.ObjectUtils
* @requires sol.common.CounterUtils
* @requires sol.common.Template
* @requires sol.common.TranslateTerms
* @requires sol.common.ObjectFormatter.TemplateSord
* @requires sol.common.WfUtils
* @requires sol.common.ix.RfUtils
* @requires sol.common.ix.FunctionBase
* @requires sol.common.ix.ConnectionUtils
*
*/
sol.define("sol.common.ix.functions.Set", {
extend: "sol.common.ix.FunctionBase",
requiredConfig: ["objId", "entries"],
/**
* @cfg types which are supported
* @private
*/
types: ["MASK", "SORD", "GRP", "MAP", "FORMBLOB", "WFMAP", "WF"],
/**
* @cfg {String} objId (required)
* Object ID
*/
/**
* @cfg {Object[]} entries (required)
* @cfg {String} entries.key field key
* @cfg {String} entries.type the type of the field {@link sol.common.ix.functions.Set#types}
* @cfg {String} entries.value the value which should be set
* @cfg {Boolean} entries.useKwl enable keyword lookup for the current value
* @cfg {Boolean} entries.useDynKwl enable dynamic keyword lookup for the current value
* @cfg {Object} entries.dynKwlCfg
* @cfg {Boolean} entries.onlyIfEmpty the value will only be set when selected field is not empty
*
* Entries that contains the values to set
*/
/**
* @cfg {String} flowId
* Flow ID
*/
/**
* @cfg {String} timeZone
* Time zone
*/
/**
* @cfg {Boolean} asAdmin
* Execute function in admin context
*/
initialize: function (config) {
var me = this;
me.$super("sol.common.ix.FunctionBase", "initialize", [config]);
me.sordMaskChanged = false;
if (me.asAdmin) {
if (me.wfDiagram) {
me.checkAdminExecutionContext(function () {
sol.common.WfUtils.checkMainAdminWf(me.wfDiagram);
});
} else {
me.checkAdminExecutionContext(function () {
sol.common.ix.RfUtils.checkMainAdminRights(sol.common.IxConnectionUtils.getCurrentUser());
});
}
if (me.timeZone) {
// We should not change ixConnectAdmin timeZone parameter because this object
// is a singleton.
throw Error("Use of an admin connection in combination with the timeZone parameter is currently not implemented");
}
}
me.connection = sol.common.IxConnectionUtils.getConnection(me.asAdmin);
},
checkAdminExecutionContext: function (callback) {
var me = this;
try {
if (!callback || !sol.common.ObjectUtils.isFunction(callback)) {
throw Error("Callback in `checkAdminExecutionContext` is not a callback function");
}
callback.call(me);
} catch (ex) {
logger.warn("Ignore `asAdmin` parameter", ex);
me.asAdmin = false;
if (me.$throwError === true) {
throw ex;
}
}
},
/**
* Sets a field value
*/
process: function () {
var me = this,
i, entry, type, func, entries;
if (!me.entries) {
return;
}
me.logger.debug(["sol.common.ix.functions.Set: entries={0}", JSON.stringify(me.entries)]);
me.entries = sol.common.ObjectUtils.clone(me.entries);
me.separatedEntries = {};
me.sordData = [];
me.sordMapKeyValues = [];
me.sordFormdataValues = []; //blob
me.wfMapKeyValues = [];
if (me.timeZone) {
me.savedTimeZone = ixConnect.loginResult.clientInfo.timeZone;
ixConnect.loginResult.clientInfo.timeZone = me.timeZone;
me.logger.debug(["user.name={0}, timeZone={1}", ixConnect.loginResult.user.name, ixConnect.loginResult.clientInfo.timeZone]);
}
me.sord = sol.common.RepoUtils.getSord(me.objId, { sordZ: SordC.mbAllIndex, connection: me.connection });
for (i = 0; i < me.entries.length; i++) {
entry = me.entries[i];
type = entry.type.toUpperCase();
if (me.types.indexOf(entry.type) < 0) {
throw "Unsupported type: " + entry.type;
}
if (!me.filterEntry(me.sord, entry)) {
me.separatedEntries[type] = me.separatedEntries[type] || [];
me.separatedEntries[type].push(entry);
}
}
for (i = 0; i < me.types.length; i++) {
type = me.types[i];
func = me["processType" + type];
entries = me.separatedEntries[type];
me.logger.debug(["separatedEntries[{0}]={1}", type, JSON.stringify(entries)]);
if (func && entries) {
func.call(me, me.separatedEntries[type]);
}
}
me.saveSordValues();
me.saveWorkflowValues();
if (me.savedTimeZone) {
ixConnect.loginResult.clientInfo.timeZone = me.savedTimeZone;
}
},
emptyFilterTypes: ["GRP", "MAP"],
filterEntry: function (sord, entry) {
var me = this;
return !!(
~me.emptyFilterTypes.indexOf(entry.type)
&& entry.onlyIfEmpty
&& String(sol.common.SordUtils.getValue(sord, entry) || "")
);
},
processTypeMASK: function (maskEntries) {
var me = this,
mask;
if (maskEntries.length > 0) {
mask = maskEntries[0].value;
if (mask && sol.common.SordUtils.docMaskExists(mask)) {
me.sord = me.connection.ix().changeSordMask(me.sord, mask, EditInfoC.mbSord).sord;
me.sordMaskChanged = true;
}
}
},
processTypeSORD: function (sordEntries) {
var me = this;
me.applyTemplates(sordEntries);
me.sordData = me.sordData.concat(sordEntries);
},
processTypeGRP: function (grpEntries) {
var me = this,
i, entry;
me.applyTemplates(grpEntries);
for (i = 0; i < grpEntries.length; i++) {
entry = grpEntries[i];
if (entry.useKwl) {
entry.value = me.getValueFromKwl(entry.key, entry.value);
} else if (entry.useDynKwl) {
entry.value = me.getValueFromDynKwl(me.sord.maskName, entry.key, entry.value, entry.dynKwlCfg, entry.useForeignKey);
}
}
me.sordData = me.sordData.concat(grpEntries);
},
processTypeMAP: function (sordMapEntries) {
var me = this,
i, entry;
me.applyTemplates(sordMapEntries);
for (i = 0; i < sordMapEntries.length; i++) {
entry = sordMapEntries[i];
me.sordMapKeyValues.push(new KeyValue(entry.key, entry.value));
}
},
processTypeFORMBLOB: function (sordMapEntries) {
var me = this, blb,
i, entry;
me.applyTemplates(sordMapEntries);
for (i = 0; i < sordMapEntries.length; i++) {
entry = sordMapEntries[i];
if (entry.asJSON) {
try {
entry.value = JSON.stringify(entry.value);
} catch (e) {
throw "SET: could not stringify value marked with option 'asJSON'. Writing to FORMBLOB field `" + entry.key + "` failed.";
}
}
blb = new MapValue((new java.lang.String(entry.key)), (new FileData("text/plain", (new java.lang.String(entry.value)).getBytes(java.nio.charset.StandardCharsets.UTF_8))));
me.sordFormdataValues.push(blb);
}
},
processTypeWFMAP: function (wfMapEntries) {
var me = this,
i, entry;
me.applyTemplates(wfMapEntries);
for (i = 0; i < wfMapEntries.length; i++) {
entry = wfMapEntries[i];
me.wfMapKeyValues.push(new KeyValue(entry.key, entry.value));
}
},
processTypeWF: function (wfEntries) {
var me = this,
i, entry;
if (!me.wfDiagram) {
return;
}
me.applyTemplates(wfEntries);
for (i = 0; i < wfEntries.length; i++) {
entry = wfEntries[i];
if (entry.key == "STATUS") {
sol.common.WfUtils.setWorkflowStatus(me.wfDiagram, entry.value);
}
}
},
applyTemplates: function (entries) {
var me = this, maxLength,
i, entry;
for (i = 0; i < entries.length; i++) {
entry = entries[i];
if (entry.useTemplating && entry.value) {
me.tplSord = me.tplSord || sol.common.WfUtils.getTemplateSord(me.sord, me.flowId, {
formBlobs: entry.useFormBlobs || false
});
entry.value = sol.create("sol.common.Template", { source: entry.value }).apply(me.tplSord);
}
if (entry.truncate === true) {
maxLength = entry.maxLength || ixConnect.CONST.SORD.lnName;
entry.value = sol.common.StringUtils.truncate(entry.value, maxLength);
}
}
},
/**
* @private
*/
saveSordValues: function () {
var me = this,
sordDirty = me.sordMaskChanged;
if (me.sordData && (me.sordData.length > 0)) {
sol.common.SordUtils.updateSord(me.sord, me.sordData);
sordDirty = true;
}
if (sordDirty) {
me.connection.ix().checkinSord(me.sord, SordC.mbAllIndex, LockC.NO);
}
if (me.sordMapKeyValues && (me.sordMapKeyValues.length > 0)) {
me.connection.ix().checkinMap(MapDomainC.DOMAIN_SORD, me.sord.id || me.objId, me.sord.id || me.objId, me.sordMapKeyValues, LockC.NO);
}
if (me.sordFormdataValues && (me.sordFormdataValues.length > 0)) { // blob
me.connection.ix().checkinMap("formdata", me.sord.id || me.objId, me.sord.id || me.objId, me.sordFormdataValues, LockC.NO);
}
},
/**
* @private
*/
saveWorkflowValues: function () {
var me = this;
if (me.wfMapKeyValues && (me.wfMapKeyValues.length > 0)) {
if (!me.flowId) {
throw "Flow ID is empty";
}
me.connection.ix().checkinMap(MapDomainC.DOMAIN_WORKFLOW_ACTIVE, me.flowId, me.sord.id || me.objId, me.wfMapKeyValues, LockC.NO);
}
},
/**
* @private
* Retrieves a value from the keyword list of the specified field.
* It checks, if one of the entries in the keyword list starts with the valuePrefix.
* @param {String} fieldName
* @param {String} valuePrefix
* @return {String} The found item from the keyword list or the valuePrefix, if nothing was found
*/
getValueFromKwl: function (fieldName, valuePrefix) {
var me = this, kwl, items, i, item;
kwl = me.connection.ix().checkoutKeywordList(fieldName, KeywordC.mbView, 30, LockC.NO);
if (kwl) {
items = kwl.children;
for (i = 0; i < items.length; i++) {
item = items[i].text;
if (item.startsWith(valuePrefix)) {
return item;
}
}
} else {
this.logger.warn(["No keywordlist for field '{0}'", fieldName]);
}
this.logger.warn(["No keywordlist match for: '{0}'", valuePrefix]);
return valuePrefix;
},
/**
* @private
* Retrieves a value from the dynamic keyword list of the spezified field.
* It checks, if one of the entries in the keyword list starts with the valuePrefix.
* @param {String} maskName
* @param {String} fieldName
* @param {String} valuePrefix
* @param {Object} config
* @param {Object} foreignKeyConfig
* @return {String} The found item from the keyword list or the valuePrefix, if nothing was found
*/
getValueFromDynKwl: function (maskName, fieldName, valuePrefix, config, foreignKeyConfig) {
var me = this, params, result;
params = { data: valuePrefix };
if (config) {
params.returnColumn = config.returnColumn;
params.filterColumn = config.filterColumn;
}
if (foreignKeyConfig) {
foreignKeyConfig.value === undefined
&& me.entries.some(function (entry) {
return (entry.key === foreignKeyConfig.key)
&& ((foreignKeyConfig.value = entry.value), true); // empty strings are ok
});
if (foreignKeyConfig.value === undefined) {
throw "No value found for foreignKey " + foreignKeyConfig.key + ". Please define an array-entry having said key or define a value directly in `useForeignKey`";
}
params.useForeignKey = foreignKeyConfig;
}
result = sol.common.SordUtils.getDynamicKeywordlistValue(maskName, fieldName, params);
if (result.length <= 0) {
this.logger.warn(["No keywordlist match for: '{0}'", valuePrefix]);
} else if (result.length > 1) {
this.logger.warn(["No unique keywordlist match for: '{0}'", valuePrefix]);
} else {
valuePrefix = result[0];
}
return result;
}
});
/**
* @member sol.common.ix.functions.Set
* @static
* @inheritdoc sol.common.ix.FunctionBase#onEnterNode
*/
function onEnterNode(clientInfo, userId, wfDiagram, nodeId) {
var params, module;
logger.enter("onEnterNode_Set", { flowId: wfDiagram.id, nodeId: nodeId });
params = sol.common.WfUtils.parseAndCheckParams(wfDiagram, nodeId, "entries");
params.objId = wfDiagram.objId;
params.flowId = wfDiagram.id;
params.wfDiagram = wfDiagram;
module = sol.create("sol.common.ix.functions.Set", params);
module.process();
logger.exit("onEnterNode_Set");
}
/**
* @member sol.common.ix.functions.Set
* @static
* @inheritdoc sol.common.ix.FunctionBase#onExitNode
*/
function onExitNode(clientInfo, userId, wfDiagram, nodeId) {
var params, module;
logger.enter("onExitNode_Set", { flowId: wfDiagram.id, nodeId: nodeId });
params = sol.common.WfUtils.parseAndCheckParams(wfDiagram, nodeId, "entries");
params.objId = wfDiagram.objId;
params.flowId = wfDiagram.id;
params.wfDiagram = wfDiagram;
module = sol.create("sol.common.ix.functions.Set", params);
module.process();
logger.exit("onExitNode_Set");
}
/**
* @member sol.common.ix.functions.Set
* @method RF_sol_function_Set
* @static
* @inheritdoc sol.common.ix.FunctionBase#RF_FunctionName
*/
function RF_sol_function_Set(ec, args) {
var params, module;
logger.enter("RF_sol_function_Set", args);
params = sol.common.ix.RfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId", "entries");
// Hint: Must never be true within an Registered function call
// because this would result in a security issue because each person can
// update each sord object within the repository
//params.asAdmin = false;
module = sol.create("sol.common.ix.functions.Set", params);
module.process();
logger.exit("RF_sol_function_Set");
}